
#include <stdio.h>

#define NCUSTOMER 2 //The number of customer per run

#define BUSY 1 //Indicate the server status is busy

#define IDLE 0 //Indicate the server status is idle

#define EXPARRIVAL 10 //The expected value or mean of interarrival time 

#define EXPSERVICE 8 //The expected value or mean of service time

#define INFINITE 1000000 //Indicate a very large value

double expon(double *, float);


int main() {

  int i,NW,j,status;
  double a,s,A,D,C,lastclock,clock,sumD,avgD,sumNW,avgNW,sumU,avgU,T,Q[NCUSTOMER],seed;

  /* 
  Variable declarations:
  i: The next customer be predicted. We predict next cutomer when all the customers before he are in the queue , serving, or served.
  NW: The total number of the customers in queue.
  j: The customer being served.
  status: The status of the server.
  a: A new interarrival time.
  s: A new service time.
  A: The next arrival event happen time.
  D: The deley time of the customer to be served just now.
  C: The next departure event happen time.
  lastclock: last event happen time.
  clock: this event happen time.
  sumD: the total deley time until now.
  avgD: the average delay time per customer in one run.
  sumNW: to compute the average number in system.
  avgNW: the average number in system in one rum.
  sumU: total busy time of server to compute the system utilization.
  avgU: the system utilization.
  T: interval between adjacent clock.
  Q[]: restore the arrival time of every customer.
  seed: the seed of random variant generator.
  */

  //Initialization
  seed = 1234567; //set the seed only once, at the start.
  i=0;
  clock=0;
  status=IDLE;
  NW=0;
  j=0;
  sumD=0;
  sumNW=0;
  sumU=0;
  a=expon(&seed,EXPARRIVAL); //generate a new interarrival time
  Q[0]=a;
  A=a;
  printf(" Predict a new arrival #%d at %f",i+1,A);
  C=INFINITE;
  //End of initialization
  while (j<NCUSTOMER){	//there is any customer not be served yet	 
	  lastclock=clock; //restore the last clock time when current clock time is going to jump to a new event happen time
	  if (C>A){//An arrival event happens
		  printf("\n An arrival event happens");		  
		  clock=A; //current clock time is going to jump to a new arrival event happen time
		  printf(" at %f",clock);		  
		  if(status==0){//Server status is idle
			  status=BUSY; //Change the server status into busy
			  printf("\n The server start to be busy");
			  D=clock-Q[j]; //Compute the delay of current customer
			  printf("\n Welcome, he has delayed %f",D);
			  sumD=sumD+D; //accumulate the total delay
			  s=expon(&seed,EXPSERVICE); //generate the service time of current customer
			  C=clock+s; //generate the departure time of current customer
			  printf("\n he will leave at %f",C);
		  }
		  else{//Server status is busy
			  T=clock-lastclock; //compute the time between last clock and current clock
			  sumNW=sumNW+T*NW; //accumulate sumNW with queue length multiplied by the time the length holds
			  NW++;	//queue length increase 1
			  printf("\n queue length is %d",NW);
			  sumU=sumU+T; //accumulate the total busy time of server
		  }
		  i++; //point to the next arrive customer
		  if (i<NCUSTOMER){	//there is any customer not arrived yet	  
			  a=expon(&seed,EXPARRIVAL); //generate the interarrival time of next arrive customer
			  Q[i]=Q[i-1]+a; //generate the arrival time of next arrive customer
			  A=Q[i]; //the next arrival event happen time
			  printf("\n Predict a new arrival #%d at %f",i+1,A);
		  }
		  else A=INFINITE; //all customers have been arrived
	  }
	  else{//A departure event happens
		  j++; //point to the next customer to be served
		  printf("\n A departure event happens");
		  clock=C; //current clock time is going to jump to a new departure event happen time
		  printf(" at %f",clock);
		  T=clock-lastclock; //compute the time between last clock and current clock
		  sumU=sumU+T; //accumulate the total busy time of server
		  if (NW==0){//Queue is empty
			  status=IDLE; //Change the server status into idle
			  printf("\n The server start to be idle");
			  C=INFINITE; //all customers have been departed
		  }
		  else{//Queue is not empty
			  sumNW=sumNW+T*NW; //accumulate sumNW with queue length multiplied by the time the length holds
			  NW--; //queue length decrease 1
			  printf("\n queue length is %d",NW);
			  D=clock-Q[j]; //Compute the delay of current customer
			  printf("\n Welcome, he has delayed %f",D);
			  sumD=sumD+D;	//accumulate the total delay
			  s=expon(&seed,EXPSERVICE); //generate the service time of current customer
			  C=clock+s; //compute the departure time of current customer
			  printf("\n he will leave at %f",C);
		  }
	  }
  }
  //Report
  printf("\n REPORT:");
  avgNW=sumNW/clock; //compute the average number in system in one rum
  printf("\n The average number in queue system is %f",avgNW);
  avgD=sumD/NCUSTOMER; //compute the average delay time per customer in one run
  printf("\n The average delay in system is %f",avgD);
  avgU=sumU/clock; //compute the system utilization
  printf("\n The server utilization is %f\n",avgU);
  //End of report
}